package com.jinyang.baserouter

import android.text.TextUtils
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.annotations.SerializedName
import com.google.gson.reflect.TypeToken
import java.io.Reader
import java.lang.UnsupportedOperationException
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.util.concurrent.ConcurrentHashMap

/**
 * @Author: LiuJinYang
 * @CreateDate: 2021/11/24
 * @Description:
 */
object GsonUtils {
    private const val KEY_DEFAULT = "defaultGson"
    private val GSONS: MutableMap<String, Gson?> = ConcurrentHashMap()


    fun setGson(key: String, gson: Gson?) {
        if (TextUtils.isEmpty(key) || gson == null) return
        GSONS[key] = gson
    }


    fun getGson(key: String): Gson? {
        return GSONS[key]
    }


    fun getGson(): Gson {

        var gsonDefault = GSONS[KEY_DEFAULT]
        if (gsonDefault == null) {
            gsonDefault = createGson()
            GSONS[KEY_DEFAULT] = gsonDefault
        }
        return gsonDefault
    }


    fun toJson(`object`: Any?): String {
        return toJson(getGson(), `object`)
    }


    fun toJson(src: Any?, typeOfSrc: Type): String {
        return toJson(getGson(), src, typeOfSrc)
    }


    private fun toJson(gson: Gson, `object`: Any?): String {
        return gson.toJson(`object`)
    }


    private fun toJson(gson: Gson, src: Any?, typeOfSrc: Type): String {
        return gson.toJson(src, typeOfSrc)
    }


    fun <T> fromJson(json: String?, type: Class<T>?): T? {
        return fromJson(getGson(), json, type)
    }


    fun <T> fromJson(json: String?, type: Type?): T? {
        return fromJson(getGson(), json, type)
    }


    fun <T> fromJson(reader: Reader, type: Class<T>): T {
        return fromJson(getGson(), reader, type)
    }


    fun <T> fromJson(reader: Reader, type: Type): T {
        return fromJson(getGson(), reader, type)
    }


    fun <T> fromJson(gson: Gson, json: String?, type: Class<T>?): T {
        return gson.fromJson(json, type)
    }


    fun <T> fromJson(gson: Gson, json: String?, type: Type?): T {
        return gson.fromJson(json, type)
    }


    fun <T> fromJson(gson: Gson, reader: Reader?, type: Class<T>): T {
        return gson.fromJson(reader, type)
    }


    fun <T> fromJson(gson: Gson, reader: Reader?, type: Type): T {
        return gson.fromJson(reader, type)
    }


    fun getListType(type: Type): Type {
        return TypeToken.getParameterized(MutableList::class.java, type).type
    }


    fun getSetType(type: Type): Type {
        return TypeToken.getParameterized(MutableSet::class.java, type).type
    }


    fun getMapType(keyType: Type, valueType: Type): Type {
        return TypeToken.getParameterized(MutableMap::class.java, keyType, valueType).type
    }


    fun getArrayType(type: Type): Type {
        return TypeToken.getArray(type).type
    }


    fun getType(rawType: Type, vararg typeArguments: Type): Type {
        return TypeToken.getParameterized(rawType, *typeArguments).type
    }


    private fun createGson(): Gson {
        return GsonBuilder().serializeNulls().disableHtmlEscaping().create();
    }

    /**
     * 解析data是object的情况
     */
    fun <T> fromJson2Object(json: String?, clazz: Class<T>): BaseHttpResponse<T>? {
        val type: Type = getType(BaseHttpResponse::class.java, clazz)
        return fromJson(json, type)
    }

    /**
     * 解析data是array的情况
     */
    fun <T> fromJson2Array(json: String?, clazz: Class<T>): BaseHttpResponse<MutableList<T?>?>? {
        // 生成List<T> 中的 List<T>
        val listType: Type = getListType(clazz)
        // 根据List<T>生成完整的BaseHttpResponse<List<T>>
        val type: Type = getType(BaseHttpResponse::class.java, listType)
        return fromJson(json, type)
    }

    /**
     * 解析data是Map的情况
     */
    fun <K, T> fromJson2Map(json: String?, clazz1: Class<K>, clazz2: Class<T>): BaseHttpResponse<MutableMap<K?, T?>?>? {
        // 生成BaseHttpResponse<Map<K,T>> 中的 Map<K,T>
        val mapType: Type = getMapType(clazz1, clazz2)
        // 根据Map<K,T>生成完整的BaseHttpResponse<Map<K,T>>
        val type: Type = getType(BaseHttpResponse::class.java, mapType)
        return fromJson(json, type)
    }


//    /**
//     * 解析data是object的情况
//     */
//    fun <T> fromJson2Object(json: String?, clazz: Class<T>?): BaseHttpResponse<T>? {
//        val type: Type = ParameterizedTypeImpl(BaseHttpResponse::class.java, arrayOf(clazz))
//        return fromJson(json, type)
//    }
//
//    /**
//     * 解析data是array的情况
//     */
//    fun <T> fromJson2Array(json: String?, clazz: Class<T>?): BaseHttpResponse<MutableList<T?>?>? {
//        // 生成List<T> 中的 List<T>
//        val listType: Type =
//            ParameterizedTypeImpl(MutableList::class.java, arrayOf(clazz))
//        // 根据List<T>生成完整的BaseHttpResponse<List<T>>
//        val type: Type = ParameterizedTypeImpl(BaseHttpResponse::class.java, arrayOf(listType))
//        return fromJson(json, type)
//    }
//
//    /**
//     * 解析data是Map的情况
//     */
//    fun <K, T> fromJson2Map(
//        json: String?,
//        clazz1: Class<K>?,
//        clazz2: Class<T>?
//    ): BaseHttpResponse<MutableMap<K?, T?>?>? {
//        // 生成BaseHttpResponse<Map<K,T>> 中的 Map<K,T>
//        val mapType: Type =
//            ParameterizedTypeImpl(MutableMap::class.java, arrayOf(clazz1, clazz2))
//        // 根据Map<K,T>生成完整的BaseHttpResponse<Map<K,T>>
//        val type: Type = ParameterizedTypeImpl(BaseHttpResponse::class.java, arrayOf(mapType))
//        return fromJson(json, type)
//    }
}

data class BaseHttpResponse<T>(
    @SerializedName(value = "code", alternate = ["Status", "status"]) var code: Int? = null,
    @SerializedName(value = "message", alternate = ["Msg", "msg"]) var message: String? = null,
    @SerializedName(value = "data", alternate = ["Data"]) var data: T? = null
)

//class ParameterizedTypeImpl(private val raw: Class<*>, args: Array<Type?>?) :
//    ParameterizedType {
//    private val args: Array<Type?> = args ?: arrayOfNulls(0)
//
//    /**
//     * 返回Map<String,User>里的String和User，所以这里返回[String.class,User.clas]
//     */
//    override fun getActualTypeArguments(): Array<Type?> {
//        return args
//    }
//
//    /**
//     * Map<String,User>里的Map,所以返回值是Map.class
//     */
//    override fun getRawType(): Type {
//        return raw
//    }
//
//    /**
//     * 用于这个泛型上中包含了内部类的情况,一般返回null
//     */
//    override fun getOwnerType(): Type? {
//        return null
//    }
//}